package wcg;

import ikelib.NumericTextField;
import ikelib.wintime;

import javax.swing.JPanel;

import java.awt.Button;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Font;
import java.awt.Frame;
import java.awt.BorderLayout;
import javax.swing.JDialog;
import java.awt.GridBagLayout;
import javax.swing.JButton;
import java.awt.GridBagConstraints;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Vector;

import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.InputEvent;

import javax.swing.ImageIcon;
import javax.swing.JScrollBar;
import javax.swing.JTextField;
import javax.swing.BoxLayout;
import javax.swing.JLabel;
import javax.swing.JComboBox;





public class DataTableViewDialog extends JDialog implements ActionListener {

	private static final long serialVersionUID = 1L;
	private JPanel jContentPane = null;
	private JPanel jPanelSouth = null;
	private JButton jButtonOK = null;
	private JScrollPane jScrollPane = null;
	private JTable jTableDataView = null; // @
	private winDataBase mDataBase = null;  //  @jve:decl-index=0:
	private wintime mDispStartTime = null;  //  @jve:decl-index=0:
	private int mDispTimeSpan = 0;
	private ArrayList<Integer> mDispChannel = null;  //  @jve:decl-index=0:
	private wintime FirstVisibleTime = null;  //  @jve:decl-index=0:
	private static int MARKER_MAX = 10;
	private wintime[] mMarkerTime = new wintime[MARKER_MAX]; //@
	
	/**
	 * マーカーをセットする
	 * @param id
	 * マーカーの番号 0:リファレンス
	 * @param tm
	 */
	public void setMarkerTime(int id , wintime tm){
		if(0<=id && id<=9){
			mMarkerTime[id] = new wintime(tm);
		}
	}
	public void setFirstVisibleTime(wintime tm){
		FirstVisibleTime = new wintime(tm);
	}
	public void setDisplayChannel(ArrayList<Integer> l){
		mDispChannel = l;
	}
	public void setWinDataBase(winDataBase db){
		mDataBase = db;
	}
	public void setDispStartTime(wintime tm){
		mDispStartTime = new wintime(tm);
		jTextFieldStartTime.setText(mDispStartTime.fmt());
	}
	public wintime getDispStartTime(){
		return new wintime(mDispStartTime);
	}
	/**
	 * 秒単位で設定
	 * @param sec
	 */
	public void setDispTimeSpan(int sec){
		mDispTimeSpan = sec;
		jTextFieldSpan.setText(String.format("%d",mDispTimeSpan));
	}
	/**
	 * @param owner
	 */
	public DataTableViewDialog(Frame owner) {
		//super(owner);
		initialize();
	}

	/**
	 * This method initializes this
	 * 
	 * @return void
	 */
	private void initialize() {
		this.setSize(894, 300);
		this.setContentPane(getJContentPane());
	}

	/**
	 * This method initializes jContentPane
	 * 
	 * @return javax.swing.JPanel
	 */
	private JPanel getJContentPane() {
		if (jContentPane == null) {
			jContentPane = new JPanel();
			jContentPane.setLayout(new BorderLayout());
			jContentPane.add(getJPanelSouth(), BorderLayout.SOUTH);  // Generated
			jContentPane.add(getJScrollPane(), BorderLayout.CENTER);  // Generated
			jContentPane.add(getJPanelNorth(), BorderLayout.NORTH);
		}
		return jContentPane;
	}

	/**
	 * This method initializes jPanelSouth	
	 * 	
	 * @return javax.swing.JPanel	
	 */
	private JPanel getJPanelSouth() {
		if (jPanelSouth == null) {
			jPanelSouth = new JPanel();
			jPanelSouth.setLayout(new GridBagLayout());  // Generated
		}
		return jPanelSouth;
	}

	/**
	 * This method initializes jButtonOK	
	 * 	
	 * @return javax.swing.JButton	
	 */
	private JButton getJButtonOK() {
		if (jButtonOK == null) {
			jButtonOK = new JButton();
			jButtonOK.setText("OK");  // Generated
			jButtonOK.addActionListener(new java.awt.event.ActionListener() {
				public void actionPerformed(java.awt.event.ActionEvent e) {
					setVisible(false);
				}
			});
		}
		return jButtonOK;
	}

	/**
	 * This method initializes jScrollPane	
	 * 	
	 * @return javax.swing.JScrollPane	
	 */
	private JScrollPane getJScrollPane() {
		if (jScrollPane == null) {
			jScrollPane = new JScrollPane();
			jScrollPane.setViewportView(getJTableDataView());  // Generated
		}
		return jScrollPane;
	}
	
	/**
	 * 
	 * @author ikechan
	 *
	 */
	public class CustomTableModel extends DefaultTableModel {
		private static final long serialVersionUID = 1L;
	    CustomTableModel(Object[][] tableData, String[] tableColumnName) {
			super(tableData,tableColumnName);
		}
	    CustomTableModel(){
	    	super();
	    }
		public Class<?> getColumnClass(int col){
			switch(col){
			case 0: return String.class;
			default: return Integer.class;
			}
		}
		
	}
	private CustomTableModel TableModel=null;//@
	private String[] TableColumnName = {"Index","Time"};
	private Object[][] TableData = {
			{new String(""),new String(""),new String("")}
	};
	private JPanel jPanelNorth = null;
	private JTextField jTextFieldStartTime = null;
	private JButton jButtonTimeSet = null;
	private JLabel jLabelMes = null;
	private JPanel jPanelNorthEeat = null;
	/**
	 * This method initializes jTableDataView	
	 * 	
	 * @return javax.swing.JTable	
	 */
	private JTable getJTableDataView() {
		if (jTableDataView == null) {
			TableModel = new CustomTableModel(TableData,TableColumnName); 	 
			jTableDataView = new JTable(TableModel); 
			jTableDataView.setAutoResizeMode(JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS);
			jTableDataView.setColumnSelectionAllowed(true);
			jTableDataView.getTableHeader().setReorderingAllowed(true);
			//jTableDataView.getColumnModel().getColumn(0).setMinWidth(200);
		}
		return jTableDataView;
	}
	private int mDataDispStyle = 1;
	private JPanel jPanel2 = null;
	private JLabel jLabelMes2 = null;
	private JComboBox jComboBoxFormat = null;
	private JLabel jLabelSpan = null;
	private JTextField jTextFieldSpan = null;
	private JPanel jPanel3 = null;
	private NumericTextField jTextFieldCalc = null;
	private JLabel jLabelCalc = null;
	
	public class DataRenderer extends DefaultTableCellRenderer {

		public DataRenderer() {
			super();
			setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
		}

		public void setValue(Object value) {
			if ((value != null) && (value instanceof Number)) {
				Number numberValue = (Number) value;
				//NumberFormat formatter = NumberFormat.getInstance();
				//   value = formatter.format(numberValue.doubleValue());
				long val;
				switch(mDataDispStyle){
				case 3:
					val = (long)numberValue.intValue();
					int hv = (int)((val >> 16)&0xffff);
					int lv =  (int)(val & 0xffff);
					if(hv ==0) {
						value = String.format("%04X",lv);
					}
					else{
						value = String.format("%4X-%04X",hv,lv);
					}
					break;
				case 2:
					value = String.format("%08X",numberValue.intValue());
					break;
				case 1:
					value = String.format("%,d",numberValue.intValue());
					break;
				default:
					value = String.format("%d",numberValue.intValue());
				}
			} 
			super.setValue(value);
		} 
		public Component getTableCellRendererComponent(JTable table,Object value,boolean isSelected,boolean hasFocus,int row,int column){
			setBackground(Color.white);
			setForeground(Color.black);
			
			int r = table.convertRowIndexToModel(row);
			int c = table.convertColumnIndexToModel(0);
			Object v = TableModel.getValueAt(r,c);
			if(v instanceof String){
				String str = (String)v;
				if(!str.isEmpty()){
				if(str.equals(">")){
					setBackground(Color.orange);
				}
					else if(str.equals("0")){
						setForeground(Color.white);
						setBackground(Color.red.brighter());
					}
					else if(Character.isDigit(str.charAt(0))){
						setForeground(Color.white);
						setBackground(Color.blue.brighter());
					}
					else {
						setForeground(Color.white);
						setBackground(Color.magenta.brighter());
					}
				}
			}
			return super.getTableCellRendererComponent(table,value,isSelected,hasFocus,row,column);
		}
	

	} 
	/**
	 * 指定の行を見えるようにする。
	 * スクロールバーを操作しているので、最初の一回は失敗する？
	 * @param rowview
	 */
	private void ensureVisible(int rowview){
		JScrollPane s = jScrollPane;
		JScrollBar vs = s.getVerticalScrollBar();//@
		float width = vs.getMaximum() - vs.getMinimum();
		float pos = width * (float)rowview  / jTableDataView.getRowCount();
		vs.setValue((int)(pos));
	}
	
	private int mCurrentFindMarkerIndex = 0;
	private JButton jButtonNextMarker = null;
	/**
	 * 次のマーカを見つけてビジブルにする
	 */
	private void findNextMarker(){
		mCurrentFindMarkerIndex++;
		if(mCurrentFindMarkerIndex>=(jTableDataView.getRowCount()-1)){
			mCurrentFindMarkerIndex=0;
		}
		int c = jTableDataView.convertColumnIndexToView(0);
		for(int i=mCurrentFindMarkerIndex;i<jTableDataView.getRowCount();i++){
			Object o = jTableDataView.getValueAt(i,c);
			if(o instanceof String){
				String s = (String)o;
				if(!s.isEmpty()){
					mCurrentFindMarkerIndex=i;
					ensureVisible(i);
					break;
				}
				
			}
			mCurrentFindMarkerIndex=i;
		}
	}
	/**
	 * 前のマーカを見つけてビジブルにする
	 */
	private void findPrevMarker(){
		mCurrentFindMarkerIndex--;
		if(mCurrentFindMarkerIndex<0){
			mCurrentFindMarkerIndex=(jTableDataView.getRowCount()-1);
		}
		int r = jTableDataView.convertColumnIndexToView(0);
		for(int i=mCurrentFindMarkerIndex;i>=0;i--){
			String s = (String)jTableDataView.getValueAt(r,i);
			if(!s.isEmpty()){
				mCurrentFindMarkerIndex=i;
				ensureVisible(i);
				break;
			}
			mCurrentFindMarkerIndex=i;
		}
	}
	/**
	 * 表示を更新する
	 */
	public boolean update(){
		//TableColumnModel cm = jTableDataView.getColumnModel();
		int dtnum = mDispChannel.size();
		// ROWをすべて削除
		int rc = TableModel.getRowCount();
		while(rc>0){
			TableModel.removeRow(rc-1);
			rc--;
		}
		// 列を合わせる
//		while(dtnum+2>jTableDataView.getColumnCount()){
//			TableModel.addColumn(new Vector());
//		}
		String[] colid = new String[dtnum+3];
		colid[0] = new String("!");
		colid[1] = new String("Index");
		colid[2] = new String("Time");
		for(int i=0;i<dtnum;i++){
			colid[3+i]=String.format("%04X",mDispChannel.get(i));
		}
		TableModel.setColumnIdentifiers(colid);
		jTableDataView.getColumn("!").setMaxWidth(10);
		jTableDataView.getColumn("Index").setPreferredWidth(45);
		jTableDataView.getColumn("Time").setPreferredWidth(220);
		jTableDataView.setDefaultRenderer(Integer.class, new DataRenderer());
		jTableDataView.setDefaultRenderer(String.class, new DataRenderer());
		
		int dataColomn = 3;
		wintime et = new wintime(mDispStartTime);
		et.inc_sec(mDispTimeSpan);
		File outfile = new File("wichkgtmp.csv");
		int line = mDataBase.doExportCSV(mDispStartTime,et,",",outfile,mDispChannel,false,true,false,0.0,false,null,1,0,null); // TODO ここＴＭＰ
		if(line>0){
			BufferedReader r;
			try {
				int index = 0;
				long tm0 = -1;
				long td0 = -1;
				long td1 = -1;
				int rowview = 0;
				if(FirstVisibleTime!=null){
					tm0 = FirstVisibleTime.getValue();
				}
				r = new BufferedReader(new FileReader(outfile));
				while(true){
					String str = r.readLine();
					if(str==null) break;
					String[] tok = str.split(",");
					int row = jTableDataView.getRowCount();
					TableModel.insertRow(row,new Object[tok.length]);					
					TableModel.setValueAt(index++, row, 1);
					TableModel.setValueAt(tok[0], row, 2);
					if(tm0>0){
						wintime wt = new wintime();
						wt.parseDaySec(tok[0]);
						td0 = wt.getValue();
						if(td1>0){
							if(td1<=tm0 && tm0<td0){
								TableModel.setValueAt(">", row, 0);
								rowview = row;
							}
							for(int i=0;i<mMarkerTime.length;i++){
								if(mMarkerTime[i]==null) continue;
								long tmmaker = mMarkerTime[i].getValue();
								if(td1<=tmmaker && tmmaker<td0){
									TableModel.setValueAt(String.format("%d",i), row, 0);
								}
							}
						}
						td1 = td0;
					}
					for(int i=1;i<tok.length;i++){
						int aValue = Integer.valueOf(tok[i]);
						TableModel.setValueAt(aValue, row, i+dataColomn-1);
					}
				}
				r.close();
				findNextMarker();
				return true;
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
			
		}
		return false;
	}
	/**
	 * This method initializes jPanelNorth	
	 * 	
	 * @return javax.swing.JPanel	
	 */
	private JPanel getJPanelNorth() {
		if (jPanelNorth == null) {
			jLabelMes = new JLabel();
			jLabelMes.setText("StartTime:");
			jPanelNorth = new JPanel();
			jPanelNorth.setPreferredSize(new Dimension(100, 30));
			jPanelNorth.setLayout(new BoxLayout(getJPanelNorth(), BoxLayout.X_AXIS));
			jPanelNorth.add(getJPanelNorthEeat(), null);
			jPanelNorth.add(getJPanel2(), null);
			jPanelNorth.add(getJPanel3(), null);
		}
		return jPanelNorth;
	}
	/**
	 * This method initializes jTextFieldStartTime	
	 * 	
	 * @return javax.swing.JTextField	
	 */
	private JTextField getJTextFieldStartTime() {
		if (jTextFieldStartTime == null) {
			jTextFieldStartTime = new JTextField();
			jTextFieldStartTime.setPreferredSize(new Dimension(180,20));
		}
		return jTextFieldStartTime;
	}
	/**
	 * This method initializes jButtonTimeSet	
	 * 	
	 * @return javax.swing.JButton	
	 */
	private JButton getJButtonTimeSet() {
		if (jButtonTimeSet == null) {
			jButtonTimeSet = new JButton();
			jButtonTimeSet.setText("SET");
			jButtonTimeSet.addActionListener(new java.awt.event.ActionListener() {
				public void actionPerformed(java.awt.event.ActionEvent e) {
					String sec = jTextFieldStartTime.getText();
					wintime nt = new wintime();
					nt.parseDaySec(sec);
					setDispStartTime(nt);
					
					sec = jTextFieldSpan.getText();
					int s = Integer.valueOf(sec);
					setDispTimeSpan(s);
					update();
				}
			});
		}
		return jButtonTimeSet;
	}
	/**
	 * This method initializes jPanelNorthEeat	
	 * 	
	 * @return javax.swing.JPanel	
	 */
	private JPanel getJPanelNorthEeat() {
		if (jPanelNorthEeat == null) {
			jLabelSpan = new JLabel();
			jLabelSpan.setText("Span[s]:");
			jPanelNorthEeat = new JPanel();
			jPanelNorthEeat.setLayout(new BoxLayout(getJPanelNorthEeat(), BoxLayout.X_AXIS));
			jPanelNorthEeat.setMaximumSize(new Dimension(300, 32));
			jPanelNorthEeat.add(getJButtonNextMarker(), null);  // Generated
			jPanelNorthEeat.add(jLabelMes, null);
			jPanelNorthEeat.add(getJTextFieldStartTime(), null);
			jPanelNorthEeat.add(jLabelSpan, null);
			jPanelNorthEeat.add(getJTextFieldSpan(), null);
			jPanelNorthEeat.add(getJButtonTimeSet(), null);
		}
		return jPanelNorthEeat;
	}
	/**
	 * This method initializes jPanel2	
	 * 	
	 * @return javax.swing.JPanel	
	 */
	private JPanel getJPanel2() {
		if (jPanel2 == null) {
			jLabelCalc = new JLabel();
			jLabelCalc.setText("Calculator:");
			jLabelMes2 = new JLabel();
			jLabelMes2.setText("Format:");
			jPanel2 = new JPanel();
			jPanel2.setPreferredSize(new Dimension(100,20));
			jPanel2.setLayout(new BoxLayout(getJPanel2(), BoxLayout.X_AXIS));
			jPanel2.add(jLabelMes2, null);
			jPanel2.add(getJComboBoxFormat(), null);
			jPanel2.add(jLabelCalc, null);
			jPanel2.add(getJTextFieldCalc(), null);
		}
		return jPanel2;
	}
	/**
	 * This method initializes jComboBoxFormat	
	 * 	
	 * @return javax.swing.JComboBox	
	 */
	private JComboBox getJComboBoxFormat() {
		if (jComboBoxFormat == null) {
			jComboBoxFormat = new JComboBox();
			jComboBoxFormat.setPreferredSize(new Dimension(160,16));
			jComboBoxFormat.addItem("Decimal");
			jComboBoxFormat.addItem("Decimal with comma");
			jComboBoxFormat.addItem("Hexadecimal");
			jComboBoxFormat.addItem("Hexadecimal with hyphen");
			jComboBoxFormat.addActionListener(this);
		}
		return jComboBoxFormat;
	}

	@Override
	public void actionPerformed(ActionEvent arg0) {
		if(arg0.getSource().equals(jComboBoxFormat)){
			mDataDispStyle = jComboBoxFormat.getSelectedIndex();
			update();
		}
		
	}
	/**
	 * This method initializes jTextFieldSpan	
	 * 	
	 * @return javax.swing.JTextField	
	 */
	private JTextField getJTextFieldSpan() {
		if (jTextFieldSpan == null) {
			jTextFieldSpan = new JTextField();
			jTextFieldSpan.setPreferredSize(new Dimension(50,20));
		}
		return jTextFieldSpan;
	}
	/**
	 * This method initializes jPanel3	
	 * 	
	 * @return javax.swing.JPanel	
	 */
	private JPanel getJPanel3() {
		if (jPanel3 == null) {
			jPanel3 = new JPanel();
			jPanel3.setPreferredSize(new Dimension(50,20));
			jPanel3.setLayout(new BoxLayout(getJPanel3(), BoxLayout.X_AXIS));
			jPanel3.add(getJButtonOK(), null);
		}
		return jPanel3;
	}
	/**
	 * This method initializes jTextFieldCalc	
	 * 	
	 * @return javax.swing.JTextField	
	 */
	private JTextField getJTextFieldCalc() {
		if (jTextFieldCalc == null) {
			jTextFieldCalc = new NumericTextField();
			jTextFieldCalc.setPreferredSize(new Dimension(100,20));
		}
		return jTextFieldCalc;
	}
	/**
	 * This method initializes jButtonNextMarker	
	 * 	
	 * @return javax.swing.JButton	
	 */
	private JButton getJButtonNextMarker() {
		if (jButtonNextMarker == null) {
			jButtonNextMarker = new JButton();
			jButtonNextMarker.setPreferredSize(new Dimension(16,16));
			jButtonNextMarker.setIcon(new ImageIcon(getClass().getClassLoader().getResource("images/marker_rounded_green.png")));
			jButtonNextMarker.addActionListener(new java.awt.event.ActionListener() {
				public void actionPerformed(java.awt.event.ActionEvent e) {
					int mod = e.getModifiers();
					if(0!=(mod & InputEvent.CTRL_DOWN_MASK)){
						findPrevMarker();
					}
					else{
						findNextMarker();
					}
				}
			});
		}
		return jButtonNextMarker;
	}

}  //  @jve:decl-index=0:visual-constraint="10,10"
